package core

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/go-kit/kit/endpoint"
	natstransport "github.com/go-kit/kit/transport/nats"
	"github.com/nats-io/nats.go"
)

func GetContextFromNatsMsg(ctx context.Context, msg *nats.Msg) context.Context {

	//for _, v := range MetaKeys {
	//	if msg.Header.Get(v) != "" {
	//		ctx = context.WithValue(ctx, v, msg.Header.Get(v))
	//	}
	//}
	for k, _ := range msg.Header {
		if msg.Header.Get(k) != "" {
			ctx = context.WithValue(ctx, k, msg.Header.Get(k))
		}
	}

	return ctx
}

func SetNatsMsgFormContext(ctx context.Context, msg *nats.Msg) context.Context {

	if msg.Header == nil {
		msg.Header = nats.Header{}
	}

	for _, key := range MetaKeys {
		value, ok := ctx.Value(key).(string)
		if ok {
			msg.Header.Set(key, value)
		}
	}

	return ctx
}

func MakeSubjectName(env, serviceName, endpointName string) string {
	return fmt.Sprintf("%s.%s.%s", env, serviceName, endpointName)
}

func NewPublisher(
	publisher *nats.Conn,
	sub string,
	options ...PublisherOption) *Publisher {
	return NewNatsPublisher(
		publisher,
		sub,
		natstransport.EncodeJSONRequest,
		DecodeNatsResponseFunc,
		options...,
	)
}

// MakeNatsClientEndpoint make nats client endpoint
func MakeNatsClientEndpoint(
	publisher *nats.Conn,
	sub string,
	options ...PublisherOption) endpoint.Endpoint {
	pub := NewPublisher(publisher, sub, options...)
	return pub.Endpoint()
}

type RequestFunc[T any] func(ctx context.Context, req any) (resp GenericResponse[T], err error)

// NewNatsClientRequest make nats client Request func
func NewNatsClientRequest[T any](
	nc *nats.Conn,
	envGroup string,
	serviceName string,
	endpointName string,
	options ...PublisherOption) RequestFunc[T] {

	options = append(options, PublisherBefore(SetNatsMsgFormContext))
	sub := MakeSubjectName(envGroup, serviceName, endpointName)
	et := MakeNatsClientEndpoint(nc, sub, options...)

	return func(ctx context.Context, req any) (resp GenericResponse[T], err error) {
		data, err := et(ctx, req)
		if err != nil {
			return resp, err
		}

		resJson, err := json.Marshal(data)
		if err != nil {
			return GenericResponse[T]{Code: 500}, err
		}

		err = json.Unmarshal(resJson, &resp)
		if err != nil {
			return GenericResponse[T]{Code: 500}, err
		}

		if resp.Code != 0 {
			return resp, errors.New("请求状态异常")
		}
		return resp, nil
	}
}
